package com.sunxboy.platform.application;

import java.io.File;
import java.io.FilenameFilter;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

class SharedContextLoader {

    private final static Logger LOG = Logger.getLogger(SharedContextLoader.class);
    private final String environment;
    private final String configHome;

    public SharedContextLoader(final String environment, final String configHome) {
        super();
        this.environment = ((environment != null) ? environment : "test.ln");
        this.configHome = ((configHome != null) ? configHome : System.getProperties().getProperty("core.home"));
    }

    public ApplicationContext loadContext(final ApplicationContext parentContext) {

        final String environmentHome = getEnvironmentHome();
        System.setProperty("env.home", environmentHome);
        final File contextPath = new File(environmentHome, "context");

        if (!contextPath.exists()) {
            LOG.warn(String.format("Shared context path %s does not exist", contextPath.getAbsolutePath()));
        }

        File[] configFiles = contextPath.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                if (name.endsWith(".xml")) {
                    return true;
                }
                return false;
            }
        });
        if (configFiles == null) {
            configFiles = new File[] {};
        }

        final Set<Resource> resources = new LinkedHashSet<Resource>();
        for (File file : configFiles) {
            resources.add(new FileSystemResource(file));
        }

        final GenericApplicationContext applicationContext = new GenericApplicationContext();
        final XmlBeanDefinitionReader xmlBeanReader = new XmlBeanDefinitionReader(applicationContext);
        for (Resource resource : resources) {
            xmlBeanReader.loadBeanDefinitions(resource);
        }
        applicationContext.setParent(parentContext);
        applicationContext.refresh();
        applicationContext.registerShutdownHook();
        return applicationContext;
    }

    private String getEnvironmentHome() {
        final String configPath = prepareHomePath(this.configHome);
        if (configPath != null) {
            LOG.info("Home is: " + configPath);
        }

        final File sharedHomePath = new File(configPath);

        if (this.environment != null) {
            LOG.info("Using enviroment id: " + this.environment);
        }
        final File sharedEnvHomePath = new File(sharedHomePath, this.environment);

        return sharedEnvHomePath.getAbsolutePath();
    }

    private String prepareHomePath(final String path) {
        /*
         * If not specified then return
         */
        if (path == null) {
            return null;
        }

        File homeFolder = new File(path);

        if (!homeFolder.exists()) {
            LOG.debug(String.format("Path %s does not exist", path));
            homeFolder.mkdirs();
            LOG.debug(String.format("Path %s is created!", path));
        }

        if (!homeFolder.isDirectory()) {
            LOG.debug(String.format("Path %s is not a folder", path));
            return null;
        }

        if (!homeFolder.canRead()) {
            LOG.debug(String.format("Path %s is not readable", path));
            return null;
        }

        return homeFolder.getPath();
    }
}
